class Bubbles extends egret.DisplayObjectContainer {
    private balls: Array<Ball>
    private numBalls: number = 5
    private centerBall: Ball
    private bouncing: number = -1
    private springging: number = 0.01

    public constructor() {
        super()
        this.once(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this)
    }

    private onAddToStage(): void {
        this.balls = new Array<Ball>()
        this.centerBall = new Ball(100, 0xCCCCCC)
        this.addChild(this.centerBall)
        this.centerBall.x = this.stage.stageWidth / 2
        this.centerBall.y = this.stage.stageHeight / 2

        for (let i = 0; i < this.numBalls; ++i) {
            let ball:Ball = new Ball(Math.random() * 40 + 5, Math.random() * 0xFFFFFF)
            ball.x = Math.random() * this.stage.stageWidth
            ball.y = Math.random() * this.stage.stageHeight
            ball.vx = Math.random() * 6 - 3
            ball.vy = Math.random() * 6 - 3
            this.addChild(ball)
            this.balls.push(ball)
        }

        this.addEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this)
    }

    private onEnterFrame() {
        for (let i = 0; i < this.numBalls; ++i) {
            let ball = this.balls[i]
            this.move(ball)
            let {isHit, angle} = this.hitTestBall(this.centerBall, ball)
            let minDist = ball.radius + this.centerBall.radius
            if (isHit) {
                let tx = this.centerBall.x + Math.cos(angle) * minDist
                let ty = this.centerBall.y + Math.sin(angle) * minDist
                ball.vx += (tx - ball.x) * this.springging
                ball.vy += (ty - ball.y) * this.springging 
            }
        }
    }

    private move(ball: Ball) {
        ball.x += ball.vx
        ball.y += ball.vy
        this.bounce(ball)
    }

    private bounce(ball: Ball) {
        if (ball.x + ball.radius > this.stage.stageWidth) {
            ball.x = this.stage.stageWidth - ball.radius
            ball.vx *= this.bouncing
        } else if (ball.x - ball.radius < 0) {
            ball.x = ball.radius
            ball.vx *= this.bouncing
        }

        if (ball.y + ball.radius > this.stage.stageHeight) {
            ball.y = this.stage.stageHeight - ball.radius
            ball.vy *= this.bouncing
        } else if (ball.y - ball.radius < 0) {
            ball.y = ball.radius
            ball.vy *= this.bouncing
        }
    }

    /**
     *  a 是基准被减的球 
     */
    private hitTestBall(a: Ball, b: Ball): { isHit: boolean, angle: number } {
        let dx = b.x - a.x
        let dy = b.y - a.y
        let point = egret.Point.create(dx, dy)
        let isHit: boolean = false
        if (point.length < a.radius + b.radius) {
            isHit = true
        }
        egret.Point.release(point)
        return { isHit, angle: Math.atan2(dy, dx) }
    }
}